package com.bing.shiro;

import com.bing.my.entity.User;
import com.bing.my.service.UserService;
import com.bing.utils.JwtUtil;
import com.bing.utils.UtilConstants;
import io.jsonwebtoken.Claims;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * 我的配置规则
 * @author Bing
 * @date 2021/10/03 19:10
 **/
@Service
public class MyRealm extends AuthorizingRealm {



    @Autowired
    private UserService userService;
    /**
     * 大坑！，必须重写此方法，不然Shiro会报错
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JwtToken;
    }


    /**
     * 授权
     *只有当需要检测用户权限的时候才会调用此方法，例如checkRole,checkPermission之类的
     * @param
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection token) {
        //解密token获取username
        Claims claims = JwtUtil.parseJWT(UtilConstants.JWT_JWT_SEC, token.toString());
        String username = (String) claims.get("username");
        //根据username查询数据库
        User user = userService.findUserByUsername(username);

        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        //添加当前用户角色
        simpleAuthorizationInfo.addRole(user.getRoles());
        // 添加当前用户权限
        //Set<String> permission = new HashSet<>(Arrays.asList(user.getPermission().split(",")));
        //simpleAuthorizationInfo.addStringPermissions(permission);
        return simpleAuthorizationInfo;
    }
    /**
     * 认证,heard有token才会运行
     * 默认使用此方法进行用户名正确与否验证，错误抛出异常即可。
     * @param
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authToken) throws AuthenticationException {
        // 获得当前用户
        String token = (String) authToken.getCredentials();
        //解密token获取username
        Claims claims = JwtUtil.parseJWT(UtilConstants.JWT_JWT_SEC, token.toString());
        String username = (String) claims.get("username");
        if (username == null) {
            throw new AuthenticationException("错误令牌");
        }
        //判读token是否过期
        if (claims.getExpiration().getTime() < System.currentTimeMillis()) {
            throw new IncorrectCredentialsException("token失效，请重新登录");
        }
        //根据username查询数据库
        User user = userService.findUserByUsername(username);
        if (user == null) {
            throw new UnknownAccountException("用户不存在!");
        }
        if (!user.getUsername().equals(username)) {
            throw new IncorrectCredentialsException("用户名或密码错误");
        }
        return new SimpleAuthenticationInfo(token, token, "my_realm");

    }
}
